"""
Script generator for converting content to natural speech scripts.

Transforms presentation content into natural, spoken language suitable for TTS.
"""

import re
from typing import List, Dict, Any, Optional
from dataclasses import dataclass

from ..parser.content_types import DocumentStructure, Section, ContentNode, ContentType
from ..utils.exceptions import MD2PPTError


@dataclass
class ScriptSegment:
    """A segment of the presentation script."""
    section_title: str
    section_level: int
    content: str
    duration_estimate: float
    slide_number: int
    metadata: Optional[Dict[str, Any]] = None
    
    def __str__(self) -> str:
        return f"Slide {self.slide_number}: {self.content[:50]}..."


@dataclass
class PresentationScript:
    """Complete presentation script."""
    title: str
    segments: List[ScriptSegment]
    total_duration: float
    total_slides: int
    metadata: Optional[Dict[str, Any]] = None
    
    def get_full_script(self) -> str:
        """Get the complete script as a single string."""
        parts = [f"# {self.title}\n"]
        
        for segment in self.segments:
            parts.append(f"\n## 第 {segment.slide_number} 页：{segment.section_title}")
            parts.append(segment.content)
        
        return "\n".join(parts)
    
    def get_script_by_slide(self, slide_number: int) -> Optional[ScriptSegment]:
        """Get script for a specific slide."""
        for segment in self.segments:
            if segment.slide_number == slide_number:
                return segment
        return None


class ScriptGenerator:
    """Generates natural language scripts from presentation content."""
    
    def __init__(self, language: str = "zh-CN", style: str = "conversational"):
        """
        Initialize script generator.
        
        Args:
            language: Target language for script
            style: Script style (conversational, formal, educational, etc.)
        """
        self.language = language
        self.style = style
        
        # Load templates based on language and style
        self._load_templates()
    
    def generate_script(self, doc_structure: DocumentStructure) -> PresentationScript:
        """
        Generate a complete presentation script.
        
        Args:
            doc_structure: Parsed document structure
            
        Returns:
            Complete presentation script
        """
        segments = []
        slide_number = 1
        total_duration = 0.0
        
        for section in doc_structure.sections:
            # Skip title slides for script generation (handled separately)
            if section.is_title_slide:
                continue
            
            # Generate script for this section
            script_content = self._generate_section_script(section, slide_number)
            
            # Estimate speaking duration
            duration = self._estimate_speaking_duration(script_content)
            
            segment = ScriptSegment(
                section_title=section.heading,
                section_level=section.level,
                content=script_content,
                duration_estimate=duration,
                slide_number=slide_number
            )
            
            segments.append(segment)
            total_duration += duration
            slide_number += 1
        
        # Add introduction and conclusion if enabled
        if self._should_add_introduction():
            intro_segment = self._generate_introduction(doc_structure.title)
            segments.insert(0, intro_segment)
            total_duration += intro_segment.duration_estimate
        
        if self._should_add_conclusion():
            conclusion_segment = self._generate_conclusion(doc_structure.title, len(segments))
            segments.append(conclusion_segment)
            total_duration += conclusion_segment.duration_estimate
        
        return PresentationScript(
            title=doc_structure.title,
            segments=segments,
            total_duration=total_duration,
            total_slides=len(segments)
        )
    
    def _generate_section_script(self, section: Section, slide_number: int) -> str:
        """Generate script for a single section."""
        script_parts = []
        
        # Add section introduction
        if section.level == 2:  # Main content slide
            intro = self._get_slide_introduction(section.heading, slide_number)
            script_parts.append(intro)
        
        # Process content nodes
        for content_node in section.content:
            content_script = self._convert_content_to_script(content_node)
            if content_script:
                script_parts.append(content_script)
        
        # Add transitions
        transition = self._get_slide_transition(slide_number)
        if transition:
            script_parts.append(transition)
        
        return " ".join(script_parts)
    
    def _convert_content_to_script(self, content_node: ContentNode) -> str:
        """Convert a content node to natural speech script."""
        if content_node.type == ContentType.TEXT:
            return self._process_text_content(content_node.data.text)
        
        elif content_node.type == ContentType.BULLET_LIST:
            return self._process_bullet_list(content_node.data.items)
        
        elif content_node.type == ContentType.IMAGE:
            return self._process_image_content(content_node.data)
        
        elif content_node.type == ContentType.VIDEO:
            return self._process_video_content(content_node.data)
        
        elif content_node.type == ContentType.CODE_BLOCK:
            return self._process_code_content(content_node.data)
        
        elif content_node.type == ContentType.ANIMATED_CONTENT:
            # Process the underlying content
            return self._convert_content_to_script(content_node.data.content)
        
        return ""
    
    def _process_text_content(self, text: str) -> str:
        """Process plain text into natural speech."""
        # Remove markdown formatting
        clean_text = self._clean_markdown(text)
        
        # Add natural speech patterns
        if self.language.startswith("zh"):
            return self._add_chinese_speech_patterns(clean_text)
        else:
            return self._add_english_speech_patterns(clean_text)
    
    def _process_bullet_list(self, items: List[str]) -> str:
        """Convert bullet list to natural speech."""
        if not items:
            return ""
        
        if self.language.startswith("zh"):
            if len(items) == 1:
                return f"我们来看这个要点：{self._clean_markdown(items[0])}。"
            
            intro = f"这里有{len(items)}个要点："
            processed_items = []
            
            for i, item in enumerate(items, 1):
                clean_item = self._clean_markdown(item)
                if i == len(items):
                    processed_items.append(f"最后，{clean_item}")
                else:
                    processed_items.append(f"第{i}，{clean_item}")
            
            return intro + "；".join(processed_items) + "。"
        else:
            # English processing
            if len(items) == 1:
                return f"Let's look at this key point: {self._clean_markdown(items[0])}."
            
            intro = f"Here are {len(items)} key points:"
            processed_items = []
            
            for i, item in enumerate(items, 1):
                clean_item = self._clean_markdown(item)
                if i == len(items):
                    processed_items.append(f"Finally, {clean_item}")
                else:
                    processed_items.append(f"Number {i}, {clean_item}")
            
            return intro + " " + "; ".join(processed_items) + "."
    
    def _process_image_content(self, image_data) -> str:
        """Generate script for image content."""
        if self.language.startswith("zh"):
            if image_data.alt_text:
                return f"现在我们来看这张图片：{image_data.alt_text}。"
            else:
                return "现在我们来看这张图片。"
        else:
            if image_data.alt_text:
                return f"Now let's look at this image: {image_data.alt_text}."
            else:
                return "Now let's look at this image."
    
    def _process_video_content(self, video_data) -> str:
        """Generate script for video content."""
        if self.language.startswith("zh"):
            if video_data.alt_text:
                return f"接下来我们观看一个视频：{video_data.alt_text}。"
            else:
                return "接下来我们观看一个视频。"
        else:
            if video_data.alt_text:
                return f"Next, let's watch this video: {video_data.alt_text}."
            else:
                return "Next, let's watch this video."
    
    def _process_code_content(self, code_data) -> str:
        """Generate script for code content."""
        if self.language.startswith("zh"):
            if code_data.language:
                return f"现在我们来看这段{code_data.language}代码。"
            else:
                return "现在我们来看这段代码。"
        else:
            if code_data.language:
                return f"Now let's look at this {code_data.language} code."
            else:
                return "Now let's look at this code."
    
    def _clean_markdown(self, text: str) -> str:
        """Remove markdown formatting from text."""
        # Remove bold and italic markers
        text = re.sub(r'\*\*([^*]+)\*\*', r'\1', text)
        text = re.sub(r'\*([^*]+)\*', r'\1', text)
        text = re.sub(r'__([^_]+)__', r'\1', text)
        text = re.sub(r'_([^_]+)_', r'\1', text)
        
        # Remove code markers
        text = re.sub(r'`([^`]+)`', r'\1', text)
        
        # Remove links but keep text
        text = re.sub(r'\[([^\]]+)\]\([^)]+\)', r'\1', text)
        
        return text.strip()
    
    def _add_chinese_speech_patterns(self, text: str) -> str:
        """Add natural Chinese speech patterns."""
        # Add pauses and natural flow
        if "。" not in text and "！" not in text and "？" not in text:
            text = text + "。"
        
        # Add connecting words for better flow
        connectors = ["那么", "接下来", "我们可以看到", "这里"]
        
        return text
    
    def _add_english_speech_patterns(self, text: str) -> str:
        """Add natural English speech patterns."""
        if not text.endswith(('.', '!', '?')):
            text = text + "."
        
        return text
    
    def _get_slide_introduction(self, title: str, slide_number: int) -> str:
        """Generate introduction for a slide."""
        if self.language.startswith("zh"):
            return f"接下来我们来看第{slide_number}页，{title}。"
        else:
            return f"Now let's move to slide {slide_number}, {title}."
    
    def _get_slide_transition(self, slide_number: int) -> str:
        """Generate transition to next slide."""
        if self.style == "conversational":
            if self.language.startswith("zh"):
                transitions = [
                    "好的，我们继续。",
                    "接下来我们看下一页。",
                    "让我们进入下一个内容。"
                ]
            else:
                transitions = [
                    "Alright, let's continue.",
                    "Now let's move to the next slide.",
                    "Let's proceed to the next topic."
                ]
            
            return transitions[slide_number % len(transitions)]
        
        return ""
    
    def _generate_introduction(self, title: str) -> ScriptSegment:
        """Generate introduction segment."""
        if self.language.startswith("zh"):
            content = f"大家好，欢迎观看《{title}》的演示。让我们开始吧。"
        else:
            content = f"Hello everyone, welcome to the presentation of {title}. Let's get started."
        
        return ScriptSegment(
            section_title="开场介绍" if self.language.startswith("zh") else "Introduction",
            section_level=1,
            content=content,
            duration_estimate=self._estimate_speaking_duration(content),
            slide_number=0
        )
    
    def _generate_conclusion(self, title: str, slide_count: int) -> ScriptSegment:
        """Generate conclusion segment."""
        if self.language.startswith("zh"):
            content = f"以上就是《{title}》的全部内容。感谢大家的观看！"
        else:
            content = f"That concludes our presentation of {title}. Thank you for watching!"
        
        return ScriptSegment(
            section_title="结束语" if self.language.startswith("zh") else "Conclusion",
            section_level=1,
            content=content,
            duration_estimate=self._estimate_speaking_duration(content),
            slide_number=slide_count + 1
        )
    
    def _estimate_speaking_duration(self, text: str) -> float:
        """Estimate speaking duration for text."""
        # Chinese: ~300 characters per minute
        # English: ~150 words per minute
        
        if self.language.startswith("zh"):
            char_count = len(text)
            return (char_count / 300) * 60  # Convert to seconds
        else:
            word_count = len(text.split())
            return (word_count / 150) * 60  # Convert to seconds
    
    def _load_templates(self):
        """Load language and style specific templates."""
        # This could be extended to load from external files
        pass
    
    def _should_add_introduction(self) -> bool:
        """Check if introduction should be added."""
        return self.style in ["conversational", "educational"]
    
    def _should_add_conclusion(self) -> bool:
        """Check if conclusion should be added."""
        return self.style in ["conversational", "educational"]


class ScriptGenerationError(MD2PPTError):
    """Raised when script generation fails."""
    pass